// 12_lifetimes.rs
// Rust 生命周期教程

fn main() {
    // 1. 生命周期避免悬垂引用
    {
        let _r;               // ---------+-- 'a
        {                     //          |
            let x = 5;        // -+-- 'b  |
            _r = &x;          //  |       |
        }                     // -+       |
        // println!("r: {}", r); //          |
    }                         // ---------+
    
    // 2. 函数中的生命周期注解
    let string1 = String::from("abcd");
    let string2 = "xyz";
    
    let result = longest(string1.as_str(), string2);
    println!("较长的字符串是: {}", result);
    
    // 3. 生命周期注解语法
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("重要摘录: {}", i.part);
    
    // 4. 生命周期省略规则
    let s: &'static str = "I have a static lifetime.";
    println!("静态生命周期字符串: {}", s);
    
    // 5. 结合泛型、Trait Bound 和生命周期
    let string1 = String::from("long string is long");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest_with_an_announcement(
            string1.as_str(),
            string2.as_str(),
            "今天使用 longest 函数",
        );
        println!("较长的字符串是22: {}", result);
    }
    // 注意：下面这行会出错，因为 result 引用了已经被释放的 string2
    // println!("较长的字符串是: {}", result);
}

// 2. 函数中的生命周期注解
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

// 3. 结构体中的生命周期注解
struct ImportantExcerpt<'a> {
    part: &'a str,
}

// 4. 生命周期省略规则示例
// fn first_word(s: &str) -> &str {  // 编译器应用了生命周期省略规则
//     let bytes = s.as_bytes();
// 
//     for (i, &item) in bytes.iter().enumerate() {
//         if item == b' ' {
//             return &s[0..i];
//         }
//     }
// 
//     &s[..]
// }

// 5. 结合泛型、Trait Bound 和生命周期
use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(
    x: &'a str,
    _y: &'a str,
    ann: T,
) -> &'a str
where
    T: Display,
{
    println!("公告: {}", ann);
    if x.len() > 5 {
        x
    } else {
        x  // 修改为返回 x，避免引用 y
    }
}

// 6. 方法中的生命周期
impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }
    
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("注意: {}", announcement);
        self.part
    }
}

// 7. 静态生命周期
// 'static 生命周期表示引用在整个程序期间都有效
// 字符串字面量具有 'static 生命周期

// 8. 生命周期约束示例
// 以下示例展示了更复杂的生命周期约束
fn complex_lifetimes<'a, 'b>(_x: &'a str, y: &'b str) -> &'b str
where
    'a: 'b,  // 'a 的生命周期必须比 'b 长
{
    y
}

// 9. 多个生命周期参数
fn multiply_lifetimes<'a, 'b>(x: &'a str, y: &'b str) -> (&'a str, &'b str) {
    (x, y)
}

// 10. 生命周期与泛型结构体
struct Ref<'a, T: 'a> {
    data: &'a T,
}

impl<'a, T> Ref<'a, T> {
    fn new(data: &'a T) -> Ref<'a, T> {
        Ref { data }
    }
    
    fn get(&self) -> &'a T {
        self.data
    }
}